package webhook

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"message-center/pkg/gerrno"
	"message-center/pkg/ginput"
	"net/http"
	"sync"
	"time"
)

type Dispatcher struct {
	client       *http.Client
	destinations map[string]string
	mu           *sync.Mutex
}

var dispatcher = &Dispatcher{
	client:       &http.Client{},
	destinations: make(map[string]string),
	mu:           &sync.Mutex{},
}

func (d *Dispatcher) Start() {
	ticker := time.NewTicker(5 * time.Second)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			d.dispatch()
		}
	}
}

func (d *Dispatcher) add(name, destination string) {
	d.mu.Lock()
	d.destinations[name] = destination
	d.mu.Unlock()
}

func (d *Dispatcher) dispatch() {
	d.mu.Lock()
	defer d.mu.Unlock()
	for user, destination := range d.destinations {
		go func(user, destination string) {
			req, err := http.NewRequest("POST", destination, bytes.NewBufferString(fmt.Sprintf("Hello %s, current time is %s", user, time.Now().String())))
			if err != nil {
				// probably don't allow creating invalid destinations
				return
			}
			resp, err := d.client.Do(req)
			if err != nil {
				// should probably check response status code and retry if it's timeout or 500
				return
			}
			fmt.Printf("Webhook to '%s' dispatched, response code: %d \n", destination, resp.StatusCode)
		}(user, destination)
	}
}

func WebHook(c *gin.Context) {
	var (
		rsp     = ginput.Gin{C: c}
		reqData = make(map[string]string)
	)

	httpCode, errCode := rsp.ParamParse(&reqData)

	if httpCode != http.StatusOK {
		rsp.SendJSON(httpCode, errCode, nil)
		return
	}

	dispatcher.add(reqData["Name"], reqData["Destination"])

	go dispatcher.Start()

	res := "发送成功！"
	rsp.SendJSON(http.StatusOK, gerrno.SUCCESS, res)
}
